/**
 *     This file is part of cesm-ws.
 *
 *     cesm-ws, Web Service for Community Earth System Model
 *
 *     Copyright (c) 2010, Purdue University and/or affilicates or thrid-party contributors as
 *     indicated by the @author tags or express copyright attribution statements
 *     applied by the authors. All third-party contributions are distributed under
 *     license by Purdue University.
 *
 *     cesm-ws is free software: you can redistribute it and/or modify
 *     it under the terms of the GNU General Public License as published by
 *     the Free Software Foundation, either version 3 of the License, or
 *     (at your option) any later version.
 *
 *     This program is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *     GNU General Public License for more details.
 *
 *     You should have received a copy of the GNU Lesser General Public License
 *     along with this distribution.  If not, see <http://www.gnu.org/licenses/>.
 */

package edu.purdue.rcac.cesm.util;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * This class parses $CESM_WSSCRIPTS/*.sh outputs
 * 
 * @author Han Zhang
 * 
 */
public class CESMLogParser {
	private String logFilePath;
	private String whole;
	private List<CESMLogElement> logs = new ArrayList<CESMLogElement>();

	// group 1: start time
	// group 2: log content
	// group 3: end time
	public static final String logPatternString = "\\s+[>]{50,80} \\[ (\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}) \\]\\s+"
			+ "(.+?)"
			+ "\\s+[<]{50,80} \\[ (\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}) \\]\\s{1}";

	// group 1: start time
	// group 2: log content
	private static final String incompleteLogPatternString = "\\s+[>]{50,80} \\[ (\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}) \\]\\s+(.+?)";

	// group 2: result
	private static final String resultPatternString = "(.*)\\[RESULT\\] (.+?)";

	// group 2: error
	private static final String errorPatternString = "(.*)\\[ERROR\\]:* (.+?)";

	public static Pattern logPattern = Pattern.compile(logPatternString,
			Pattern.DOTALL);
	public static Pattern incompleteLogPattern = Pattern.compile(
			incompleteLogPatternString, Pattern.DOTALL);
	public static Pattern resultPattern = Pattern.compile(resultPatternString,
			Pattern.DOTALL);
	public static Pattern errorPattern = Pattern.compile(errorPatternString,
			Pattern.DOTALL);

	public List<CESMLogElement> getLogs() {
		return logs;
	}

	public void setLogs(List<CESMLogElement> logs) {
		this.logs = logs;
	}

	public String getLogFilePath() {
		return logFilePath;
	}

	public CESMLogParser(File file) {
		try {
			BufferedReader reader = new BufferedReader(new FileReader(file));
			this.logFilePath = file.getAbsolutePath();
			while (reader.ready()) {
				whole += reader.readLine() + "\n";
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			whole = "";
		} catch (IOException e) {
			e.printStackTrace();
			whole = "";
		}
	}

	public CESMLogParser(String whole) {
		if (whole != null)
			this.whole = whole;
		else
			this.whole = "";
		this.logFilePath = "";
	}

	public void parse() throws IllegalArgumentException {
		Matcher logMatcher = logPattern.matcher(whole);
		String rest = "";
		while (logMatcher.find()) {
			String content = logMatcher.group(0);
			String startTime = logMatcher.group(1);
			String log = logMatcher.group(2);
			String endTime = logMatcher.group(3);
			CESMLogElement element = new CESMLogElement(startTime, endTime,
					content);
			Matcher resultMatcher = resultPattern.matcher(log);
			Matcher errorMatcher = errorPattern.matcher(log);

			if (resultMatcher.matches()) {
				element.setResult(resultMatcher.group(2));
				element.setErrorOccured(false);
			}
			if (errorMatcher.matches()) {
				element.setError(logMatcher.group(2));
				element.setErrorOccured(true);
			}
			logs.add(element);
			rest = whole.substring(logMatcher.end());
		}
		if (!rest.trim().equals("")) {
			System.out.println("REST" + rest + "REST");
			Matcher incompleteMatcher = incompleteLogPattern.matcher(rest);
			if (incompleteMatcher.matches()) {
				String startTime = incompleteMatcher.group(1);
				String content = incompleteMatcher.group(0);
				CESMLogElement element = new CESMLogElement(startTime, content);
				logs.add(element);
			}
		}
	}

	public boolean isLatestLogReady() {
		if (logs.size() < 1)
			parse();
		if (logs.size() >= 1) {
			return true;
		}
		return false;
	}

	public CESMLogElement getLatestLog() {
		if (isLatestLogReady()) {
			return logs.get(logs.size() - 1);
		} else {
			return null;
		}
	}

	public static void main(String[] args) {
		String logFile = "/home/ba01/u113/zhang292/gouts/create_case.gout";
		CESMLogParser a = new CESMLogParser(logFile);
		System.out.println("LATEST: " + a.getLatestLog());
	}
}
